#include "StdAfx.h"
#include "TempFile.h"

TempFile::TempFile(void)
{ 
	bIsEmpty = true;
	bIsClosed = true;
	pBuffer = NULL;
	hFile = INVALID_HANDLE_VALUE;
	hFileMapping = NULL;
}
TempFile::~TempFile(void)
{
	if( pBuffer != NULL )
		UnmapViewOfFile( pBuffer);
	if (hFile != INVALID_HANDLE_VALUE) 
		CloseHandle( hFile );
	if(hFileMapping != NULL) 
		CloseHandle( hFileMapping );
}

int TempFile::Init( wstring strFileName , long nSizeOfBuffer )
{
	lBufferLength = nSizeOfBuffer;

	// Open file and get the size
	DWORD dwFileSizeHigh;
	hFile = CreateFile( strFileName.c_str(), GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_FLAG_SEQUENTIAL_SCAN , NULL );
	if( hFile == INVALID_HANDLE_VALUE )
	{
		return FILE_SYSTEM_READING_ERROR;
	}
	hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 
	if( hFileMapping == NULL )
	{
		CloseHandle( hFile );
		hFile = INVALID_HANDLE_VALUE;
		return MEMORY_ALLOCATION_ERROR;
	}
	lFileSize = GetFileSize( hFile , &dwFileSizeHigh );
	lFileSize |= (((__int64) dwFileSizeHigh) << 32);

	if( lFileSize <= 0 )
	{
		CloseHandle( hFile );
		hFile = INVALID_HANDLE_VALUE;
		CloseHandle( hFileMapping );
		hFileMapping = NULL;
		return FILE_SYSTEM_READING_ERROR;
	}
	// Set the pointer to the begin of reading file
	lFileOffset = 0;
	// Set the pointer to begin of mapped part of file in memory
	nBufferPointer = 0;

	// Map the first part of file
	if ( lFileSize < lBufferLength * sizeof(int) )
			lBufferLength = lFileSize / sizeof(int);

	pBuffer = (int*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD) (lFileOffset >> 32) , (DWORD)(lFileOffset & 0xFFFFFFFF) , (DWORD)(lBufferLength*sizeof(int)) );
	if( pBuffer == NULL )
	{
		CloseHandle(hFile);
		hFile = INVALID_HANDLE_VALUE;
		CloseHandle(hFileMapping);
		hFileMapping = NULL;
		return MEMORY_ALLOCATION_ERROR;
	}
	if( lFileSize != 0 ) bIsEmpty = false;
	// Collection is ready to work
	bIsClosed = false;
	return 0;
}
int TempFile::GetPresenter()
{
	return pBuffer[nBufferPointer];
}

int TempFile::GetLowerElement()
{
	int nValue = pBuffer[nBufferPointer];
	nBufferPointer++;

	if( nBufferPointer == lBufferLength )
	{
		UnmapViewOfFile( pBuffer );
		pBuffer = NULL;
		// go to the next part of file
		lFileOffset += lBufferLength*sizeof(int); 
		lFileSize -= lBufferLength*sizeof(int);
		if( lFileSize <= 0 )
		{
			// readed to the end
			bIsEmpty = true;
			CloseHandle(hFile);
			hFile = INVALID_HANDLE_VALUE;
			CloseHandle(hFileMapping);
			hFileMapping = NULL;
			bIsClosed = true;
		}else{
			if ( lFileSize < lBufferLength * sizeof(int) )
				lBufferLength = lFileSize / sizeof(int); 
			// will garantedly divide, because file is consist of 4-byte writes
			pBuffer = (int*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD) (lFileOffset >> 32) , (DWORD)(lFileOffset & 0xFFFFFFFF) , (DWORD)(lBufferLength*sizeof(int)) );
			if( pBuffer == NULL )
			{
				CloseHandle(hFile);
				hFile = INVALID_HANDLE_VALUE;
				CloseHandle(hFileMapping);
				hFileMapping = NULL;
				return MEMORY_ALLOCATION_ERROR;
			}
			// Set to the start of mapped part of file
			nBufferPointer = 0;
		}
	}
	return nValue;
}